package com.example.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelUtil {

	//每次开启线程数量
	private static Integer threadNumber = 1;
	
	/**
	 * 生成Excel
	 * @author YixinCapital -- buxiangpeng
	 * @throws InterruptedException 
	 */
	public static byte[] excelDownloadc(List<String> listTitleName,List<Map<String, String>> listMap) throws InterruptedException {
		//第一步创建workbook  
		XSSFWorkbook wb = new XSSFWorkbook();
		
        //第二部创建sheet页，并设置标题名称
        Sheet sheet = createXSSFSheetTitleRow(wb, listTitleName);
        		
        //第三步定义每个单元格的样式
        CellStyle  style = wb.createCellStyle();      
        style.setAlignment(CellStyle.ALIGN_CENTER);  //居中  
        
        //根据线程总数量分配每个线程处理excel数据的数量
        List<int[]> listIntArray =  allotExcelNumber(listMap.size());
        //使用线程池进行线程管理  
        ExecutorService es = Executors.newCachedThreadPool();
        //使用计数栅栏   
        CountDownLatch doneSignal = new CountDownLatch(threadNumber);
        for (int[] is : listIntArray) {
        	es.submit(new PoiWriter(sheet, listMap, is[0], is[1],doneSignal,style));
		}
        doneSignal.await();  
        es.shutdown();  
        //第五步转成流并返回
        byte[] filebyte = HSSFWorkbookCaseByteArray(wb);
        return filebyte;  
	}

	/**
	 * 根据线程总数量分配每个线程处理excel数据的数量
	 * @author YixinCapital -- buxiangpeng
	 */
	private static List<int[]> allotExcelNumber(int allSize) {
		List<int[]> listIntArray = new ArrayList<>();
		int chu = allSize/threadNumber;
		for (int i = 1; i <= threadNumber; i++ ) {
			listIntArray.add(new int[] {(i - 1) * chu ,Math.min(allSize - 1, chu * i - 1)});
		}
		return listIntArray;
	}

	/**
	 * 把work转成byte数组
	 * 
	 * @param wb word
	 * @return 
	 * @author YixinCapital -- buxiangpeng
	 *	       2017年10月11日 下午6:52:22
	 */
	private static byte[] HSSFWorkbookCaseByteArray(XSSFWorkbook wb) {
		byte[] filebyte = null;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		try {
 			wb.write(out);
 			filebyte = out.toByteArray();
 		} catch (IOException e) {
 			e.printStackTrace();
 		} finally {//使用finally块来关闭输出流
 			try {
 				if (out != null) {
 					out.close();
 				}
 			} catch (IOException ex) {
 				ex.printStackTrace();
 			}
 		}
		return filebyte;
	}	
	
	/**
	 * 创建sheet页，并设置title名称
	 * @param wb HSSFWorkbook
	 * @param listTitleName 标题名称list集合
	 * @return 
	 * @author YixinCapital -- buxiangpeng
	 *	       2017年10月11日 下午6:41:55
	 */
	private static Sheet createXSSFSheetTitleRow(XSSFWorkbook wb,List<String> listTitleName) {
		//第一步创建sheet,并设置sheet名称
		Sheet sheet = wb.createSheet();
		for(int i = 0 ; i < listTitleName.size() ; i++) {
			sheet.setColumnWidth(i, 20 * 250);
		}
		
		//第二步定义每个单元格的样式
        CellStyle  style = wb.createCellStyle();      
        style.setAlignment(CellStyle.ALIGN_CENTER);  //居中  
        Font font = wb.createFont();
        font.setBoldweight(Font.BOLDWEIGHT_BOLD);//标题加粗
        style.setFont(font);
		
		//第三步创建标题行:添加表头第0行 
        Row row1 = sheet.createRow(0);  
		
        //第四步循环设置每列的标题名称，并设设置样式
        for(int i = 0 ; i < listTitleName.size() ; i++) {
        	Cell cell = row1.createCell(i);
    		cell.setCellValue(listTitleName.get(i));
    		cell.setCellStyle(style);
        }
		return sheet;
	}
	
	public static class PoiWriter implements Runnable{
		
		private Sheet sheet;
		
        private int start;  
        
        private int end;  
        
        private final CountDownLatch doneSignal; 
        
        private CellStyle  style;
        
        private List<Map<String, String>> listMap;
  
        public PoiWriter(Sheet sheet, List<Map<String, String>> listMap, int start, int end,CountDownLatch doneSignal,CellStyle  style) {  
            this.sheet = sheet;  
            this.start = start;  
            this.end = end; 
            this.doneSignal = doneSignal;
            this.style = style;
            this.listMap = listMap;
        }

		public void run() {
			System.out.println("启动一个****");
			int i = start;
			while(i <= end) {
				//创建一行
	        	Row row = getRow(sheet, i + 1);//sheet.createRow(); 
	        	Map<String, String> mapStr = listMap.get(i);
	        	
	        	Cell cell0 = row.createCell(0);
	    		cell0.setCellValue(mapStr.get("name"));
	    		cell0.setCellStyle(style);
	    		
	    		Cell cell20 = row.createCell(1);
	    		cell20.setCellValue(mapStr.get("age"));
	    		cell20.setCellStyle(style);
				i++;
			}
			doneSignal.countDown();  
			System.out.println("结束一个****"+doneSignal.getCount());
		}  
		
		private static synchronized Row getRow(Sheet sheet, int rownum) {   
	        return sheet.createRow(rownum);  
	    } 
	}
}
